﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Convertor.Interface;

namespace Convertor
{
    /// <summary>
    /// Plugin items, use for saving to disk
    /// </summary>
    [Serializable]
    public class PluginItem : IPluginItem, IPluginMemo, INotifyPropertyChanged, ISerializable, ICloneable
    {
        private string uiqueId;

        public string UiqueId
        {
            get { return uiqueId ?? (uiqueId = Guid.NewGuid().ToString()); }
        }

        public PluginItem(string path, object @object)
        {
            this.Path = path;
            var info = @object as IPluginInfo;
            this.Name = info.Name;
            this.Description = info.Description;
            this.IsSelected = info.IsSelected;
            this.Order = info.Order;
            var config = @object as IPluginConfig;
            if (config != null)
            {
                Config = config.Config;
            }
            if (ChildPlugins == null)
            {
                ChildPlugins = new ObservableCollection<IPluginItem>();
            }
        }

        public PluginItem(string path, object @object, IPluginItem parentPlugin)
            : this(path, @object)
        {

            this.ParentPlugin = parentPlugin;
        }

        public override string ToString()
        {
            return this.Name;
        }

        #region IPluginInfo 成员

        private string name;
        /// <summary>
        /// 
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string description;
        /// <summary>
        /// 
        /// </summary>
        public string Description
        {
            get { return description; }
            set { description = value; }
        }
        private int order;
        /// <summary>
        /// 
        /// </summary>
        public int Order
        {
            get { return order; }
            set { order = value; }
        }
        private bool isSelected;
        /// <summary>
        /// 
        /// </summary>
        public bool IsSelected
        {
            get { return isSelected; }
            set { isSelected = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("IsSelected")); } }
        }
        private bool isExpanded;
        /// <summary>
        /// 
        /// </summary>
        public bool IsExpanded
        {
            get { return isExpanded; }
            set { isExpanded = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("IsExpanded")); } }
        }

        #endregion

        #region IPluginConfig 成员

        private object config;
        /// <summary>
        /// Plugin config content(Config must be serializable)
        /// </summary>
        public object Config
        {
            get { return config; }
            set { config = value; }
        }

        #endregion

        #region IPluginPath 成员

        private string path;
        /// <summary>
        /// Plugin physic path
        /// </summary>
        public string Path
        {
            get { return path; }
            set { path = value; }
        }

        #endregion

        #region ISelectedPlugin 成员

        private ObservableCollection<IPluginItem> childPlugins;
        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<IPluginItem> ChildPlugins
        {
            get { return childPlugins; }
            set { childPlugins = value; }
        }
        private IPluginItem parentPlugin;
        /// <summary>
        /// 
        /// </summary>
        public IPluginItem ParentPlugin
        {
            get { return parentPlugin; }
            set { parentPlugin = value; }
        }

        #endregion

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IPluginMemo 成员

        private string memo;

        public string Memo
        {
            get { return memo; }
            set { memo = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Memo")); } }
        }

        #endregion

        #region ISerializable 成员

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Path", Path, typeof(string));
            info.AddValue("Name", Name, typeof(string));
            info.AddValue("Description", Description, typeof(string));
            info.AddValue("Memo", Memo, typeof(string));
            info.AddValue("UiqueId", UiqueId, typeof(string));
            info.AddValue("Order", Order, typeof(int));
            info.AddValue("IsExpanded", IsExpanded, typeof(bool));
            info.AddValue("Config", Config, typeof(object));
            info.AddValue("ChildPlugins", ChildPlugins, typeof(ObservableCollection<IPluginItem>));
            info.AddValue("ParentPlugin", ParentPlugin, typeof(IPluginItem));
        }

        public PluginItem(SerializationInfo info, StreamingContext context)
        {
            // Reset the property value using the GetValue method.
            Path = (string)info.GetValue("Path", typeof(string));
            Name = (string)info.GetValue("Name", typeof(string));
            Description = (string)info.GetValue("Description", typeof(string));
            Memo = (string)info.GetValue("Memo", typeof(string));
            uiqueId = (string)info.GetValue("UiqueId", typeof(string));
            Order = (int)info.GetValue("Order", typeof(int));
            IsExpanded = (bool)info.GetValue("IsExpanded", typeof(bool));
            Config = (object)info.GetValue("Config", typeof(object));
            ChildPlugins = (ObservableCollection<IPluginItem>)info.GetValue("ChildPlugins", typeof(ObservableCollection<IPluginItem>));
            ParentPlugin = (IPluginItem)info.GetValue("ParentPlugin", typeof(IPluginItem));
        }

        #endregion

        #region ICloneable 成员

        public object Clone()
        {
            PluginItem item = new PluginItem(this.path, Convertor.Config.GlobalConfig.AllPlugins[this.path], null);
            item.Config = this.config;
            item.Memo = this.memo;
            if (this.ChildPlugins != null)
            {
                foreach (PluginItem i in this.ChildPlugins)
                {
                    item.ChildPlugins.Add((IPluginItem)i.Clone());
                }
            }
            return item;
        }

        #endregion
    }
}
